/******************************************************************************
*@file  : app.c
*@brief : SPI Slave Demos 
******************************************************************************/
#include  "app.h"


#define BUFFER_LENGTH    (256)

uint8_t TxBuffer[BUFFER_LENGTH];
uint8_t RxBuffer[BUFFER_LENGTH];

SPI_HandleTypeDef SPI_Handle;
uint32_t data_len = 128;

void printf_buff_byte(uint8_t* buff, uint32_t length)
{
	uint32_t i;

	for(i = 0; i < length; i++)
	{
		printf("%.2x ",buff[i]);	
	}
	printf("\n");
}

void SPI_Init(void)
{
    SPI_Handle.Instance                 = SPI1;
    SPI_Handle.Init.SPI_Mode            = SPI_MODE_SLAVE;
    SPI_Handle.Init.SPI_Work_Mode       = SPI_WORK_MODE_0;
    SPI_Handle.Init.X_Mode              = SPI_1X_MODE;
    SPI_Handle.Init.First_Bit           = SPI_FIRSTBIT_MSB;
    SPI_Handle.Init.Slave_SofteCs_En    = SPI_SLAVE_SOFT_CS_DISABLE;
    HAL_SPI_Init(&SPI_Handle);
}

void SPI_Slave_Comm_LOOP(void)
{
    uint32_t i;
    
    
    
    printfS("SPI Slave Comm LOOP Demo. (should connect to another board running SPI Master Comm Demo, & Slave should run first)\r\n\r\n");

    SPI_Init();
    
    //printfS("Please press the USR_PB button to continue......\r\n\r\n");
    
    //while(GPIO_PIN_SET == BSP_PB_GetState());
    
    printfS("SPI slave is running......\r\n");
    
    while (1) 
    {
        HAL_SPI_Receive(&SPI_Handle, RxBuffer, data_len, 0);
        while(HAL_SPI_GetRxState(&SPI_Handle) != SPI_RX_STATE_IDLE);
        if(SPI_Handle.Rx_Count)
        {
            printf_buff_byte(RxBuffer, SPI_Handle.Rx_Count);
            HAL_SPI_Transmit(&SPI_Handle, RxBuffer, SPI_Handle.Rx_Count, 0);
            
            printf("Rx_Count = %d. Tx_Count = %d.\r\n", SPI_Handle.Rx_Count, SPI_Handle.Tx_Count);
        }
        for (i = 0; i < data_len; i++)
        {
            RxBuffer[i] = 0;
        }
    }
}

void SPI_Slave_Comm_IT(void)
{
    uint32_t i;
    
    printfS("SPI Slave Comm IT Demo. (should connect to another board running SPI Master Comm Demo, & Slave should run first)\r\n\r\n");

    SPI_Init();
    
    //printfS("Please press the USR_PB button to continue......\r\n\r\n");
    
    //while(GPIO_PIN_SET == BSP_PB_GetState());
    
    printfS("SPI slave is running......\r\n");
    
    while (1) 
    {
        HAL_SPI_Receive_IT(&SPI_Handle, RxBuffer, data_len);        
        HAL_SPI_WaitRxTimeout(&SPI_Handle, 10000000);
        
        if(SPI_Handle.Rx_Count)
        {
            HAL_SPI_Transmit_IT(&SPI_Handle, RxBuffer, SPI_Handle.Rx_Count);
            HAL_SPI_WaitTxTimeout(&SPI_Handle, 10000000);
            
            printf("Rx_Count = %d. Tx_Count = %d.\r\n", SPI_Handle.Rx_Count, SPI_Handle.Tx_Count);
            for (i = 0; i < data_len; i++)
            {
                RxBuffer[i] = 0;
            }
        }
    }
}

void SPI_Slave_FullDuplex_Test(void)
{
    uint32_t i;
    
    uint32_t COM_OK  = 0;
    uint32_t COM_Err = 0;

    SPI_Init();
    
    printfS("SPI Slave Full Duplex Test is Ready!!! \r\n");
    
    while (1) 
    {
        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            TxBuffer[i] = i+1;
            RxBuffer[i] = 0;
        }
                                
        HAL_SPI_TransmitReceive(&SPI_Handle, TxBuffer, RxBuffer, data_len, 0);
        
        for (i = 0; i < data_len; i++)
        {
            if (TxBuffer[i] != (RxBuffer[i]+1)) 
            {
                printfS("There is one mistake : TxBuffer[%d]: 0x%02x != RxBuffer[%d]: 0x%02x \r\n", i,TxBuffer[i], i, RxBuffer[i]);
                
                COM_Err++;
            }
            else 
            {
                COM_OK++;
            }
        }
        
        printfS("SPI Slave Full Duplex Test OK count %d times \r\n",  COM_OK);
        printfS("SPI Slave Full Duplex Test Err count %d times \r\n", COM_Err);
    }
}

void SPI_Slave_Test(enum_TEST_MODE_t fe_Mode)
{        
    switch (fe_Mode)
    {
        case TEST_SLAVE_COMM_LOOP: 
            SPI_Slave_Comm_LOOP();
            break; 
        
        case TEST_SLAVE_COMM_FULLDUPLEX:
            SPI_Slave_FullDuplex_Test();
            break;
        
        case TEST_SLAVE_COMM_IT:
            SPI_Slave_Comm_IT();
            break; 

        default: break;     
    }
}
